use crate::config::AppConfig;
use crate::field::FieldTypes;
use sqlx::{Pool};
use sqlx::{MySqlConnection};
use rand::Rng;
use regex::{Regex};
use std::thread;
use std::time::Duration;
use std::sync::mpsc;
use async_std::sync::Arc;

async fn insert_data(app_config: &Arc<AppConfig>, pool: &Arc<Pool<MySqlConnection>>){
    let vals: Vec<&str> =app_config.values();
    let val_types: Vec<&str> = app_config.value_types();
    let field_count = vals.len();
    //println!("vals: {}", vals[0]);



    let mut sql=String::from(app_config.insert_sql());
    let r = Regex::new(r"values (.*)").unwrap();
    let val_sql = &r.captures_iter(app_config.insert_sql()).enumerate().next().unwrap().1[1];

    let append_val_sql_count=app_config.batch_count()-1;
    for _ in 0..append_val_sql_count {
        sql.push_str(",");
        sql.push_str(val_sql);
    }
    //println!("sql: {}", sql);

    let mut query =sqlx::query(&sql);
    let val_sql_count=app_config.batch_count()-0;
    //println!("val_sql_count: {}", val_sql_count);
    for _ in 0..val_sql_count {
        let secret_number = rand::thread_rng().gen_range(1, 9999);
        //println!("secret_number: {}", secret_number);
        for i in 0..field_count{
            let field_type = FieldTypes::from(val_types[i]);
            //println!("field idx:{},field_type: {}", i, field_type.name());
            match field_type {
                FieldTypes::String => {
                    let str_val=vals[i].replace("{}",&secret_number.to_string());
                    query=query.bind(str_val);
                },
                FieldTypes::I32 => {
                    let i32_val: i32 = vals[i].replace("{}",&secret_number.to_string()).parse().unwrap();
                    query=query.bind(i32_val);
                },
                FieldTypes::I64 => {
                    let i64_val: i64 = vals[i].replace("{}",&secret_number.to_string()).parse().unwrap();
                    query=query.bind(i64_val);
                },
                FieldTypes::F32 => {
                    let f32_val: f32 = vals[i].replace("{}",&secret_number.to_string()).parse().unwrap();
                    query=query.bind(f32_val);
                },
                FieldTypes::F64 => {
                    let f64_val: f64 = vals[i].replace("{}",&secret_number.to_string()).parse().unwrap();
                    query=query.bind(f64_val);
                },
                _ =>{
                    let str_val=vals[i].replace("{}",&secret_number.to_string());
                    query=query.bind(str_val);
                }
            }
        }
    }

    // query=query.bind(personName);
    // query=query.bind(18);
    // query=query.bind(175);
    // query=query.bind(20);
    let connect = pool.acquire().await;
    if let Ok(conn) = connect {
        //let affect_rows =query.execute(conn).await;
        let affect_rows = query.execute(conn).await;
        //affect_rows.unwrap()
        //let now:NaiveDateTime = Local::now().naive_local();
        //println!("{} 插入{:?}条",now, affect_rows);

        //conn.close().await;
    }
}

pub async fn generate_data(tx : &mpsc::Sender<i64>,app_config: &Arc<AppConfig>, pool: &Arc<Pool<MySqlConnection>>){
    let sleep_milli_second: u64 = app_config.sleep_milli_second()+0;
    loop {
        insert_data(app_config,pool).await;
        tx.send(*app_config.batch_count() as i64);
        //sender.send(threadIndex);
        thread::sleep(Duration::from_millis(sleep_milli_second));
    }
}